﻿using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Net;
using System.ServiceModel.Web;
using PeoplesJukebox.Core;
using PeoplesJukebox.Core.Enums;
using PeoplesJukebox.Core.MediaItems;
using PeoplesJukebox.Core.MediaItems.Bases;
using PeoplesJukebox.Services.Helpers;

namespace PeoplesJukebox.Services
{
    /// <summary>
    /// WCF REST implementation of media catalogue service
    /// </summary>
    public class CatalogueService : ICatalogueService
    {
        /// <summary>
        /// Returns an <see cref="Artist"/>
        /// </summary>
        /// <example>
        /// http://localhost/PeoplesJukebox.Services/CatalogueService.svc/artist/2
        /// </example>
        /// <param name="artistId">Artist ID</param>
        /// <returns>Artist</returns>
        [WebGet(UriTemplate = "artist/{artistId}", ResponseFormat = WebMessageFormat.Xml)]
        public Artist GetArtist(string artistId)
        {
            Artist item = null;
            int id = ArgumentHelper.GetId(artistId);
            if (id > -1)
            {
                item = (Artist)Container.Catalogue.GetArtist(id);
                WebOperationContext.Current.OutgoingResponse.StatusCode = HttpStatusCode.OK;
            }
            return item;
        }

        /// <summary>
        /// Returns an <see cref="Album"/>
        /// </summary>
        /// <example>
        /// http://localhost/PeoplesJukebox.Services/CatalogueService.svc/album/0
        /// </example>
        /// <param name="artistId">Album ID</param>
        /// <returns>Album</returns>
        [WebGet(UriTemplate = "album/{albumId}", ResponseFormat = WebMessageFormat.Xml)]
        public Album GetAlbum(string albumId)
        {
            Album item = null;
            int id = ArgumentHelper.GetId(albumId);
            if (id > -1)
            {
                item = (Album)Container.Catalogue.GetAlbum(id);
                WebOperationContext.Current.OutgoingResponse.StatusCode = HttpStatusCode.OK;
            }
            return item;
        }

        /// <summary>
        /// Returns a <see cref="Track"/>
        /// </summary>
        /// <example>
        /// http://localhost/PeoplesJukebox.Services/CatalogueService.svc/track/17
        /// </example>
        /// <param name="artistId">Track ID</param>
        /// <returns>Track</returns>
        [WebGet(UriTemplate = "track/{trackId}", ResponseFormat = WebMessageFormat.Xml)]
        public Track GetTrack(string trackId)
        {
            Track item = null;
            int id = ArgumentHelper.GetId(trackId);
            if (id > -1)
            {
                item = (Track)Container.Catalogue.GetTrack(id);
                WebOperationContext.Current.OutgoingResponse.StatusCode = HttpStatusCode.OK;
            }
            return item;
        }

        /// <summary>
        /// Searches all media items for the given search term
        /// </summary>
        /// <example>
        /// http://localhost/PeoplesJukebox.Services/CatalogueService.svc/any/ro
        /// </example>
        /// <param name="searchTerm">Search term</param>
        /// <returns>Collection of matches</returns>
        [WebGet(UriTemplate = "any/{searchTerm}", ResponseFormat = WebMessageFormat.Xml)]
        public Collection<MediaItem> Search(string searchTerm)
        {
            List<MediaItem> items = Container.Catalogue.Search(searchTerm);
            return new Collection<MediaItem>(items);
        }

        /// <summary>
        /// Gets all the <see cref="Track"/>s for the given <see cref="Artist"/>
        /// </summary>
        /// <example>
        /// http://localhost/PeoplesJukebox.Services/CatalogueService.svc/tracks/artist/1
        /// </example>
        /// <param name="artistId">Artist ID</param>
        /// <returns>Collection of tracks</returns>
        [WebGet(UriTemplate = "tracks/artist/{artistId}", ResponseFormat = WebMessageFormat.Xml)]
        public Collection<MediaItem> GetArtistTracks(string artistId)
        {
            List<Track> items = Container.Catalogue.GetTracksByArtist(ArgumentHelper.GetId(artistId));
            List<MediaItem> list = items.ConvertAll<MediaItem>(delegate(Track item)
                                          { return (MediaItem)item; });
            return new Collection<MediaItem>(list);
        }

        /// <summary>
        /// Gets all the <see cref="Track"/>s for the given <see cref="Album"/>
        /// </summary>
        /// <example>
        /// http://localhost/PeoplesJukebox.Services/CatalogueService.svc/tracks/album/1
        /// </example>
        /// <param name="albumId">Album ID</param>
        /// <returns>Collection of tracks</returns>
        [WebGet(UriTemplate = "tracks/album/{albumId}", ResponseFormat = WebMessageFormat.Xml)]
        public Collection<MediaItem> GetAlbumTracks(string albumId)
        {
            List<Track> items = Container.Catalogue.GetTracksByAlbum(ArgumentHelper.GetId(albumId));
            List<MediaItem> list = items.ConvertAll<MediaItem>(delegate(Track item)
            { return (MediaItem)item; });
            return new Collection<MediaItem>(list);
        }

        /// <summary>
        /// Returns all <see cref="Artist"/>s
        /// </summary>
        /// <example>
        /// http://localhost/PeoplesJukebox.Services/CatalogueService.svc/artists
        /// </example>
        /// <returns>Collection of artists</returns>
        [WebGet(UriTemplate = "artists", ResponseFormat = WebMessageFormat.Xml)]
        public Collection<MediaItem> GetArtists()
        {
            List<Artist> items = Container.Catalogue.Artists;
            List<MediaItem> list = items.ConvertAll<MediaItem>(delegate(Artist item)
            { return (MediaItem)item; });
            return new Collection<MediaItem>(list);
        }

        /// <summary>
        /// Returns all <see cref="Album"/>s
        /// </summary>
        /// <example>
        /// http://localhost/PeoplesJukebox.Services/CatalogueService.svc/albums
        /// </example>
        /// <returns>Collection of albums</returns>
        [WebGet(UriTemplate = "albums", ResponseFormat = WebMessageFormat.Xml)]
        public Collection<MediaItem> GetAlbums()
        {
            List<Album> items = Container.Catalogue.Albums;
            List<MediaItem> list = items.ConvertAll<MediaItem>(delegate(Album item)
            { return (MediaItem)item; });
            return new Collection<MediaItem>(list);
        }

        /// <summary>
        /// Returns all <see cref="Track"/>s
        /// </summary>
        /// <example>
        /// http://localhost/PeoplesJukebox.Services/CatalogueService.svc/tracks
        /// </example>
        /// <returns>Collection of tracks</returns>
        [WebGet(UriTemplate = "tracks", ResponseFormat = WebMessageFormat.Xml)]
        public Collection<MediaItem> GetTracks()
        {
            List<Track> items = Container.Catalogue.Tracks;
            List<MediaItem> list = items.ConvertAll<MediaItem>(delegate(Track item)
            { return (MediaItem)item; });
            return new Collection<MediaItem>(list);
        }

        /// <summary>
        /// Returns a collection of randomly-chosen <see cref="Track"/>s
        /// </summary>
        /// <example>
        /// http://localhost/PeoplesJukebox.Services/CatalogueService.svc/tracks/random/10
        /// </example>
        /// <param name="count">Number of random tracks to return</param>
        /// <returns>Collection of tracks</returns>
        [WebGet(UriTemplate = "tracks/random/{count}", ResponseFormat = WebMessageFormat.Xml)]
        public Collection<MediaItem> GetTrackSuggestions(string count)
        {
            int randomCount = ArgumentHelper.GetId(count);
            List<Track> items = Container.RandomTrackList.GetRandomUnplayedTracks(randomCount);
            List<MediaItem> list = items.ConvertAll<MediaItem>(delegate(Track item)
            { return (MediaItem)item; });
            return new Collection<MediaItem>(list);
        }

        /// <summary>
        /// Returns <see cref="Artist"/>s with names matching search criteris
        /// </summary>
        /// <example>
        /// http://localhost/PeoplesJukebox.Services/CatalogueService.svc/artists/the 
        /// </example>
        /// <param name="artistName">Name to search for</param>
        /// <returns>Collection of artists</returns>
        [WebGet(UriTemplate = "artists/{artistName}", ResponseFormat = WebMessageFormat.Xml)]
        public Collection<MediaItem> SearchArtists(string artistName)
        {
            List<MediaItem> list = Container.Catalogue.Search(artistName, MediaItemType.Artist);
            return new Collection<MediaItem>(list);
        }

        /// <summary>
        /// Returns <see cref="Album"/>s with names matching search criteris
        /// </summary>
        /// <example>
        /// http://localhost/PeoplesJukebox.Services/CatalogueService.svc/albums/for 
        /// </example>
        /// <param name="artistName">Name to search for</param>
        /// <returns>Collection of albums</returns>
        [WebGet(UriTemplate = "albums/{albumName}", ResponseFormat = WebMessageFormat.Xml)]
        public Collection<MediaItem> SearchAlbums(string albumName)
        {
            List<MediaItem> list = Container.Catalogue.Search(albumName, MediaItemType.Album);
            return new Collection<MediaItem>(list);
        }

        /// <summary>
        /// Returns <see cref="Tracks"/>s with names matching search criteris
        /// </summary>
        /// <example>
        /// http://localhost/PeoplesJukebox.Services/CatalogueService.svc/tracks/re 
        /// </example>
        /// <param name="artistName">Name to search for</param>
        /// <returns>Collection of tracks</returns>
        [WebGet(UriTemplate = "tracks/{trackName}", ResponseFormat = WebMessageFormat.Xml)]
        public Collection<MediaItem> SearchTracks(string trackName)
        {
            List<MediaItem> list = Container.Catalogue.Search(trackName, MediaItemType.Track);
            return new Collection<MediaItem>(list);
        }
    }
}
